/**********************************************
 * Jonathan Woolery & Ricardo Tijero
 *
 * Program 4 - Tiny FS
 * *******************************************/
#include "libDisk.h"
#include "libTinyFS.h"

/*int disk_num[MAX_DISKS];*/
/*int lastFileIndex = 0;*/

int format (int disk)
{
    unsigned int magic, superBlk, freeBlk;
    int i;
    magic = MAGIC_NUM;
    superBlk = SUPERBLOCK;
    freeBlk = FREE;

    char nullArr[252];
    for (i = 0; i < DATA_SIZE; i++)
        nullArr[i] = 0;
    /* move file descriptor to the beginning of the file*/
    if ((lseek(disk, SUPER_LOC, SEEK_SET)) < 0)
    {
        fprintf(stderr,"%d lseek: %s\n", __LINE__, strerror(errno));
        return -1;
    }             
    /* Set block code for superblock*/
    if (write (disk, &superBlk, 1) < 0)
    {
        fprintf(stderr,"%d fwrite:", __LINE__);
        return -1;
    }
    /* Set Magic number for disk*/
    if (write (disk, &magic, 1) < 0)
    {
        fprintf(stderr,"%d fwrite:", __LINE__);
        return -1;
    }

    /*zero out rest of supperBlock*/
    if (write (disk, nullArr, blockSize - 2) < 0)
    {
        fprintf(stderr,"%d fwrite:", __LINE__);
        return -1;
    }
    
    for (i = 1; i < MAX_BLOCKS; i++)
    {
        if ((lseek(disk, i * blockSize, SEEK_SET)) < 0)
        {
            fprintf(stderr,"%d lseek: %s\n", __LINE__, strerror(errno));
            return -1;
        }             

        if (write (disk, &freeBlk, 1) < 0)
        {
            fprintf(stderr,"%d fwrite:", __LINE__);
            return -1;
        }
        
        if (write (disk, &magic, 1) < 0)
        {
            fprintf(stderr,"%d fwrite:", __LINE__);
            return -1;
        }
    }
    
    return 0;
}

int isFormated(int disk)
{
    char byte;
    int formated = 1;
    int i;  
        
    for (i = 0; i < MAX_BLOCKS; i++)
    {
        if ((lseek(disk, (i * blockSize) + 1, SEEK_SET)) < 0)
        {
            fprintf(stderr,"%d lseek: %s\n", __LINE__, strerror(errno));
            return -1;
        }             
        
        if (read (disk, &byte, 1) < 0)
        {
            fprintf(stderr,"%d fread:", __LINE__);
            return -1;
        }


        if (byte != MAGIC_NUM)
        {
            formated = 0;
            break;
        }
    }
    return formated;
}

/**
 * Arguments: -filename : name of file to open
 *            -nBytes   : number of bytes to be used for metta data
 * Return: on success returns disk number. on error -1.
 * Description:
 */
int openDisk(char *filename, int nBytes)
{
    int fd;
    char endOfile = EOF;

    if(nBytes > 0)
    {
        if ((fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0)
        {
            fprintf(stderr,"%d open: %s\n", __LINE__, strerror(errno));
            return -1;
        }             

        format (fd);
        if ((lseek(fd, nBytes, SEEK_SET)) < 0)
        {
            fprintf(stderr,"%d lseek: %s\n", __LINE__, strerror(errno));
            return -1;
        }             
        if ((write(fd, &endOfile, 1)) < 0)
        {
            fprintf(stderr,"%d write: %s\n", __LINE__, strerror(errno));
            return -1;
        }             
    }
    else
    {
        if ((fd = open(filename, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0)
        {
            fprintf(stderr,"%d open: %s\n", __LINE__, strerror(errno));
            return -1;
        }

        if(isFormated(fd) == 0)
        {
            format (fd);
        }
    }

    /*return lastFileIndex++;*/
    return fd;
}

/**
 * Arguments: -disk : disk number
 *            -bNum : block number
 *            -block: block to write
 * Return: on success returns 0. on error -1.
 * Description:
 */
int readBlock(int disk, int bNum, void *block)
{

   /* if (fp == NULL)
    {
        fprintf(stderr,"%d invalid Disk", __LINE__);
        return -1;
    }*/

    if(lseek ( disk, (blockSize * bNum), SEEK_SET) < 0)
    {
        fprintf(stderr, "lseek error");
        return -1;
    }

    if (read (disk, block, blockSize) < 0)
    {
        fprintf(stderr,"%d fread:", __LINE__);
        return -1;
    }

    return 0;
}

/**
 * Arguments: -disk : disk number
 *            -bNum : block number
 *            -block: block to write
 * Return: on success returns 0. on error -1.
 * Description:
 */
int writeBlock(int disk, int bNum, void *block)
{
   /* if (fp == NULL)
    {
        fprintf(stderr,"%d invalid Disk", __LINE__);
        return -1;
    }      */

    if(lseek (disk, (blockSize * bNum), SEEK_SET) < 0)
    {
        fprintf(stderr, "lseek error");
        return -1;
    }

    if (write (disk, block, blockSize) < 0)
    {
        fprintf(stderr,"%d fwrite:", __LINE__);
        return -1;
    }

    return 0;
}
